﻿using System.Collections.Generic;
using MarriageFertility.Actions;
using MarriageFertility.Helpers;
using MarriageFertility.Mcm;
using MarriageFertility.Missions;
using MarriageFertility.Texts;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.Localization;

namespace MarriageFertility.Dialogs;

public static class DuelDialog
{
    private static DuelManager.DuelFightTypeEnum _duelFightTypeEnum;

    public static void AddDialogs(CampaignGameStarter campaignGameStarter)
    {
        AddDuelForSpouseServiceDialogs(campaignGameStarter);
        AddSparringServiceDialogs(campaignGameStarter);
    }

    private static void AddDuelForSpouseServiceDialogs(CampaignGameStarter campaignGameStarter)
    {
        campaignGameStarter.AddPlayerLine("duel_for_spouse_start", "hero_main_options", "duel_for_spouse_request",
            DuelText.DuelForSpouseProposal, CanDuelForSpouse, null);

        campaignGameStarter.AddDialogLine("duel_for_spouse_agree", "duel_for_spouse_request", "close_window",
            DuelText.DuelForSpouseAgree, AgreeToDuel, DuelStart);

        campaignGameStarter.AddDialogLine("duel_for_spouse_deny", "duel_for_spouse_request", "hero_leave",
            DuelText.DuelForSpouseDeny, CanDenyDuel, null);
    }

    private static void AddSparringServiceDialogs(CampaignGameStarter campaignGameStarter)
    {
        campaignGameStarter.AddPlayerLine("sparring_start", "hero_main_options", "sparring_request",
            DuelText.SparringInvitation, CanSparring, null);

        campaignGameStarter.AddDialogLine("sparring_agree", "sparring_request", "sparring_ask",
            DuelText.SparringAgreement, null, null);

        campaignGameStarter.AddPlayerLine("sparring_battle_many", "sparring_ask", "sparring_with_many",
            DuelText.SparringBattleMany, null, null);

        campaignGameStarter.AddPlayerLine("sparring_with_return", "sparring_ask", "sparring_return",
            DuelText.SparringReturn, null, null);

        campaignGameStarter.AddDialogLine("sparring_with_many_agree", "sparring_with_many", "close_window",
            DuelText.SparringWithManyAgree, null,
            () => ShowCompanionSelectionInquiry(DuelManager.DuelFightTypeEnum.Multiple));

        campaignGameStarter.AddDialogLine("sparring_return_agree", "sparring_return", "close_window",
            DuelText.SparringReturnAgree, null, null);
    }

    private static bool CanDuelForSpouse()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return MCMSettings.Instance.EnableDuelSpouseDialog && hero != null && hero.Spouse != null &&
               Hero.MainHero.Spouse != null && !hero.IsSpouse(Hero.MainHero);
    }

    private static void DuelStart()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (hero != null)
        {
            DuelManager.DuelFightResult = DuelManager.DuelFightResultEnum.None;
            DuelManager.DuelHero = hero.CharacterObject;
            DuelManager.WinCallEvent = () => DuelWin(hero);
            DuelManager.LoseCallEvent = DuelLoss;
            DuelManager.DuelMenuTitle = DuelText.DuelMenuTitle.SetTextVariable("HERO_NAME", hero.Name).ToString();
            DuelManager.DuelFightType = DuelManager.DuelFightTypeEnum.Single;
            GameMenu.SwitchToMenu(DuelManager.MdMenu);
        }
    }

    private static void DuelWin(Hero hero)
    {
        Hero spouse = hero.Spouse;
        DivorceAction.Apply(hero,spouse);
        Hero.MainHero.ForceMarry(spouse);
        TextObject message = DuelText.DuelWinMessage.SetTextVariable("HERO_NAME", hero.Name);
        MBInformationManager.AddQuickInformation(message);
    }

    private static void DuelLoss()
    {
        Hero spouse = Hero.MainHero.Spouse;
        DivorceAction.Apply(Hero.MainHero, spouse);
        DuelManager.DuelHero.HeroObject.ForceMarry(spouse);
        TextObject message =
            DuelText.DuelLossMessage.SetTextVariable("HERO_NAME", DuelManager.DuelHero.HeroObject.Name);
        MBInformationManager.AddQuickInformation(message);
    }

    private static bool AgreeToDuel()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return hero != null && hero.GetRelationWithPlayer() >= 0;
    }

    private static bool CanDenyDuel()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return hero != null && hero.GetRelationWithPlayer() < 0;
    }

    private static bool CanSparring()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return hero != null && hero.IsPlayerClanCompanion();
    }


    private static void ShowCompanionSelectionInquiry(DuelManager.DuelFightTypeEnum duelFightTypeEnum)
    {
        _duelFightTypeEnum = duelFightTypeEnum;
        List<InquiryElement> inquiryElements = GetCompanionInquiryElements();
        MBInformationManager.ShowMultiSelectionInquiry(
            new MultiSelectionInquiryData(DuelText.SelectCompanionTitle.ToString(),
                DuelText.SelectCompanionDescription.ToString(), inquiryElements, true, 1, 1000,
                CommonText.Confirm,
                CommonText.Cancel, SparringWithSelectedCompanions, CancelSparringWithSelectedCompanions, null), true);
    }

    private static List<InquiryElement> GetCompanionInquiryElements()
    {
        List<InquiryElement> elements = new List<InquiryElement>();
        foreach (var hero in Hero.MainHero.Clan.Heroes)
        {
            if (hero != Hero.MainHero && PartyBase.MainParty.MemberRoster?.Contains(hero.CharacterObject) == true)
            {
                elements.Add(new InquiryElement(hero, hero.Name.ToString(),
                    new ImageIdentifier(CharacterCode.CreateFrom(hero.CharacterObject))));
            }
        }

        return elements;
    }


    private static void SparringWithSelectedCompanions(List<InquiryElement> selectedCompanions)
    {
        DuelManager.DuelEnemies.Clear();
        foreach (var element in selectedCompanions)
        {
            Hero companion = element.Identifier as Hero;
            if (companion != null)
            {
                DuelManager.DuelEnemies.Add(companion.CharacterObject);
            }
        }

        DuelManager.DuelFightResult = DuelManager.DuelFightResultEnum.None;
        DuelManager.WinCallEvent = SparringWin;
        DuelManager.LoseCallEvent = SparringLose;
        DuelManager.DuelMenuTitle = DuelText.SparringMenuTitle.ToString();
        DuelManager.DuelFightType = _duelFightTypeEnum;
        GameMenu.ActivateGameMenu(DuelManager.MdMenu);
    }

    private static void CancelSparringWithSelectedCompanions(List<InquiryElement> selectedCompanions)
    {
        DuelManager.DuelFightResult = DuelManager.DuelFightResultEnum.PlayerWon;
    }

    private static void SparringWin()
    {
        TextObject message = DuelText.SparringWinMessage;
        MBInformationManager.AddQuickInformation(message);
        foreach (var duelEnemy in DuelManager.DuelEnemies)
        {
            ChangeRelationAction.ApplyPlayerRelation(duelEnemy.HeroObject, 5);
        }

        DuelManager.DuelEnemies.Clear();
    }

    private static void SparringLose()
    {
        TextObject message = DuelText.SparringLossMessage;
        MBInformationManager.AddQuickInformation(message);
        foreach (var duelEnemy in DuelManager.DuelEnemies)
        {
            ChangeRelationAction.ApplyPlayerRelation(duelEnemy.HeroObject, 2);
        }

        DuelManager.DuelEnemies.Clear();
    }
}